from http.client import responses

from django.core.handlers.base import reset_urlconf
from django.shortcuts import render

# 导入json
from django.http import JsonResponse

# 导入与redis链接模块
from django_redis import get_redis_connection
from urllib3 import request

from utils.views import LoginRequiredJSONMixin
# 导入用户模型
from .models import User

# 导入视图类
from django.views import View

# 导入 json模块
import json

# 导入正则模块
import re

# 导入时间模块
import time

# 导入哈希库模块
import hashlib

# 导入随机数
import random

# 导入云通讯
from ronglian_sms_sdk import SmsSDK

from django.contrib.auth import authenticate, login, logout

# Create your views here.

# 判断用户名是否重复的功能

# GET usernames/(?P<username>[a-zA-Z0-9_-]{5,20})/count/

# 前端: 当用户输入用户名后,失去焦点,发送一个axios(ajax)请求

# 后端:
#      请求:  接收用户名
#      业务逻辑:
#                根据用户名查询数据库,如果查询结果数量等于0,说明没有注册,
#                如果查询的数量等于1,有注册.
#      响应:
#           JSON  {"code":0,"count":0/1,"error_message":ok}
#      步骤:
#           1.接收用户名:
#           2.根据用户名查询数据库:
#           3.返回响应
class UserNameCountView(View):

    def get(self,request,username):
        """
        为了复用使用django自带的转换器类
        # 1.接收用户名,正则表达式
        if not re.match('[a-zA-Z0-9]{5,20}',username):
            return JsonResponse({"code":200,"errmsg":"用户名符合规范"})
        """

        # 2.根据用户名查询数据库

        count = User.objects.filter(username=username).count()

        return JsonResponse({'code':0,'count':count,"errmsg":"ok"})
"""

    前端: 当用户输入 用户名,密码,确认密码,手机号,是否统一协会之后,会点击注册按钮,前端会发送axios请求
    
    后端:
        请求:    接收请求JSON,获取数据
        业务逻辑: 验证数据,数据入库
        响应:     JSON{"code":0,"errmsg":"ok"}
    
        路由: POST register/
        
        步骤:
            1.接收请求(POST-----JSON)
            2.获取数据
            3.验证数据
                3.1 用户名,密码,确认密码,手机号,是否同意协议,
                3.2 用户名满足规则,用户名不能重复
                3.3 密码是否满足规则
                3.4 确认密码和密码要一致
                3.5 手机号满足规则,手机号也不能重复
                3.6 需要同意协议
            4.数据入库
            5.返回响应
"""
class RegisterView(View):
    def post(self,request):
        body_str = request.body.decode('utf-8')
        body_dict = json.loads(body_str)
        print(body_dict)
        # 获取数据
        username = body_dict.get('username')
        password = body_dict.get('password')
        password2 = body_dict.get('password2')
        mobile = body_dict.get('mobile')
        allow = body_dict.get('allow')

        # 验证数据
        # all[(xxx,xxx,xxx)] 里的元素,只要是None 就返回False 否则返回 True
        if not all([username,password,password2,mobile,allow]):
            return JsonResponse({"code":400,'errmsg':"参数不全"})

        # 用户名满足规则,用户名不能重复
        if not re.match("[a-zA-Z0-9]{5,20}",username):
            return JsonResponse({"code":400,"errmsg":"用户名不满足规则"})

        # 这个密码不加密
        # user=User(username=username,password=password,mobile=mobile)
        # user.save()

        # 这个密码就加密
        user=User.objects.create_user(
            username=username,
            password=password,
            mobile=mobile)

        # 注册成功后直接登录,返回官网首页
        # 注册成功后跳转到登录首页进行登录

        # 如何设置session信息
        # user_id = request.session['userid']

        # 系统(Django)为我们提供了 状态保持的方法
        from django.contrib.auth import login
        # request, user,
        # 状态保持  -- 登录用户的状态保持
        # user 是已经登录的用户信息
        login(request, user)

        return JsonResponse({"code":0,"errmsg":"ok"})

class MobileView(View):
    def get(self,request,mobiles):
        # http://www.mfy.site:8000/mobiles/18743173982/count/
        # 验证手机号是否合法

        # 数据库查询手机号是否存在
        total = User.objects.filter(mobile=mobiles).count()
        return JsonResponse({"code":200,"errmsg":"ok","count":total})

"""
前端:
    当用户输入完,手机号,图片验证码之后,前端就会发送一个AXIOS请求
    http://www.mfy.site:8000/sms_codes/
    18743173982/?
    image_code=HJUU&
    image_code_id=d77ceefe-e821-4dca-bc19-a66f363441ff
    

后端:
    请求:     接收请求,获取请求参数(路由有手机号,用户的图片验证码和UUID在查询字符串中)
    业务逻辑:  验证参数,验证图片验证码,生成短信验证码,保存验证码,发送短信验证码
    响应:     返回响应
            {"code":0,"errmsg":"ok"}
    steps:
        1. 获取请求参数
        2. 验证参数
        3. 验证图片验证码
        4. 生成短信验证码
        5. 保存短信验证
        6. 发送短信验证码
        7. 返回响应
"""
class SmsCodeView(View):

    def get(self,request,mobiles):

        image_code = request.GET.get('image_code')
        uuid = request.GET.get('image_code_id')

        if not all([image_code,uuid]):
            return JsonResponse({"code":666,"errmsg":"error"})

        # 验证图片验证码
        # 连接redis服务
        redis_client = get_redis_connection('capt')
        redis_image_code = redis_client.get(uuid)  # 字节串
        if redis_image_code.decode() is None:
            return JsonResponse({"code":400,"errmsg":"图片验证码已经过期"})
        if redis_image_code.decode() != image_code:
            return JsonResponse({"code":400,"errmsg":"图片验证码错误"})


        # 提取发送短信的标记,看看有没有
        send_flag = redis_client.get(f'send_flag_{mobiles}')
        if send_flag:
            return JsonResponse({"code":400,"errmsg":"不要频繁发送"})

        # 生成短信验证码,云通讯只支持4位验证码
        variable = random.randint(1000,9999)

        # redis流水线相当重要,减少拦截次数,和网络传输带宽
        # 建立redis流水线对象
        pipeline = redis_client.pipeline()

        redis_client.setex(mobiles,300,variable)
        # 设置个键
        redis_client.setex("send_flag_%s" %mobiles,60,1)
        # 执行管道
        pipeline.execute()

        # 发送短信验证码
        # from utils import SMS
        # res = SMS.send(mobiles,(variable,5))

        # 配置Celery 效率提升
        from my_celery.tasks import celery_send
        celery_send.delay(mobiles,(variable,5))


        # 判断是否成功发送
        return JsonResponse({"code":200,"errmsg":"验证码发送成功"})

"""
登录:
     POST http://www.mfy.site:8000/login/
    password: "123456798"
    username: "18743173982"
    remembered: false
前端:
    当用户把用户名和密码输入完成之后,会点击登录按钮,这个时候前端应该发送一个aiox的请求
后端:
    请求: POST请求
    业务逻辑:  验证用户名和密码是否正确session
    响应: 返回JSON数据 0 成功 , 400 失败
    
步骤:
    1.接收数据
    2.验证数据
    3.验证用户名和密码是否正确
    4.session
    5.判断是否记住登录
    5.返回响应
"""
class LoginView(View):

    def post(self,request):
        data = json.loads(request.body.decode('utf-8'))
        # 获取用户名
        username = data.get('username')
        # 获取密码
        password = data.get('password')
        # 获取状态
        remembered = data.get('remembered')

        if not all([username,password]):
            return JsonResponse({"code":400,"errmsg":"参数不全"})

        # 确定根据手机号查询还是用户名查询
        # USERNAME_FILED 字段来影响authenticate 就是根据USERNAME_FILED 来查询
        if re.match("1[3-9]\d{9}",username):
            # USERNAME_FILED 字段很重要
            User.USERNAME_FIELD ='mobile'
        else:
            User.USERNAME_FIELD ='username'

        """
        # 第一种方法
        userCount = User.objects.filter(username=username).count()
        phoneCount = User.objects.filter(mobile=username).count()
        if userCount == 0 or phoneCount == 0:
            return JsonResponse({"code":400,"errmsg":"用户名不存在"})
        """

        # 第二种方法,检测用户名 和 密码
        user = authenticate(username=username,password=password)

        if user is None:
            return JsonResponse({"code":400,"errmsg":"账户或密码错误"})

        # session
        login(request, user)

        # 判断是否记住登录
        if remembered:
            # 记住登录 -- 2周 或者 1个月  具体多场时间
            request.session.set_expiry(None)
        else:
            # 不记住登录
            request.session.set_expiry(0)

        my_responses = JsonResponse({"code":0,"errmsg":"ok"})

        # 为了首页显示用户信息
        my_responses.set_cookie('username',username)
        # print(my_responses.cookies.get('username'))
        # 返回响应
        return my_responses

class LogoutView(View):

    def delete(self,request):

        # 1.删除session_id信息
        logout(request)
        response = JsonResponse({"code":0,"errmsg":"ok"})
        # 2.删除cookie信息,因为前端是根据cookie信息判断是否登录
        response.delete_cookie('username')

        return response
"""
    第一种方法
from django.contrib.auth.mixins import AccessMixin
class LoginRequiredJSONMixin(AccessMixin):
    Verify that the current user is authenticated.

    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_authenticated:
            return JsonResponse({"code": 0, "errmsg": "ok"})
        return super().dispatch(request, *args, **kwargs)
        
"""

# 判断用户是否登录
# 面向对象重写
"""
from django.contrib.auth.mixins import LoginRequiredMixin

class LoginRequiredJSONMixin(LoginRequiredMixin):
    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_authenticated:
            return JsonResponse({"code": 0, "errmsg": "ok"})
        return super().dispatch(request, *args, **kwargs)
"""
from utils.views import LoginRequiredJSONMixin
class CenterView(LoginRequiredJSONMixin,View):
    """
        用户中心,也必须是登录用户,我们需要返回JSON数据
        难点: LoginRequiredMixin 未登录的用户会返回HTTPRESPONSES数据,不是JSON数据
    """
    def get(self,request):

        return JsonResponse({"code":0,"errmsg":"ok"})
